program sudoku;
uses crt;
var baris, kolom, i: integer;
    s, mem : array [1..9,1..9] of integer;
    init : array [1..9,1..9] of boolean;
    fin, impossible : boolean;
    chemin : string;

procedure make_box;
var li, co, cv, ch : integer;
begin
clrscr;
writeln('SUDOKU - Artificial Intelligence');
writeln();

for cv := 0 to 2 do begin  // Main Baris
   for li := 1 to 3 do begin // Mengisi maks jumlah baris pada Main Baris
        write(' '); // Mengisi inisialisasi baris
        for ch := 0 to 2 do begin  // Main Kolom selanjutnya
            for co := 1 to 3 do // Mengisi maks jumlah kolom pada Main Kolom
                if s[cv*3+li,ch*3+co] > 0 then
                   write(s[cv*3+li,ch*3+co],' ')
                else
                   write(' ');
            if ch < 2 then write (chr(179), ' ');
        end;
        writeln(' ');
    end;
    if cv < 2 then begin  // --begin garis bawah--
       write(chr(196));
       for ch := 0 to 2 do begin
           for co := 1 to 3 do write (chr(196),chr(196));
           if ch < 2 then write (chr(197), chr(196));
       end;
       writeln(' ');
    end; // --end garis bawah--
end;
writeln('       ',chr(179),'       ',chr(179));
end;




function verifikasi_baris(li : integer) : boolean;
var t : array [0..9] of integer; j : integer;
begin
     for j := 1 to 9 do t[j] := 0;
     for j := 1 to 9 do t[s[li,j]] := t[s[li,j]] + 1;
     verifikasi_baris := true;
     for j := 1 to 9 do
         if t[j] > 1 then verifikasi_baris := false;
end;


function verifikasi_kolom(co : integer) : boolean;
var t : array [0..9] of integer; j : integer;
begin
     for j := 1 to 9 do t[j] := 0;
     for j := 1 to 9 do t[s[j,co]] := t[s[j,co]] + 1;
     verifikasi_kolom := true;
     for j := 1 to 9 do
         if t[j] > 1 then verifikasi_kolom := false;
end;

function verifikasi_sudoku (li, co : integer) : boolean;
var t : array [0..9] of integer; ch, cv, j  : integer;
begin
     cv := (li-1) div 3;
     ch := (co-1) div 3;
     for j := 1 to 9 do t[j] := 0;
     for co := 1 to 3 do
          for li := 1 to 3 do
              t[s[li+cv*3,co+ch*3]] := t[s[li+cv*3,co+ch*3]] + 1;
     verifikasi_sudoku := true;
     for j := 1 to 9 do
         if t[j] > 1 then verifikasi_sudoku := false;
end;

function sudo_maju : boolean;
var t: boolean;
begin
   if kolom = 9 then begin
      baris := baris + 1;
      kolom := 1;
   end else
      kolom := kolom + 1;
   if baris = 10 then t := false
   else t := true;
   sudo_maju := t;
   if init[baris,kolom] and t then sudo_maju := sudo_maju;
end;

function sudo_back : boolean;
var t : boolean;
begin
   if kolom = 1 then begin
      baris := baris - 1;
      kolom := 9;
   end else
      kolom := kolom - 1;
   if baris = 0 then begin
      t := false;
   end else t := true;
   sudo_back := t;
   if init[baris,kolom] and t then sudo_back := sudo_back;
end;

function sudoku : boolean;
begin
fin := false; impossible := false;
while not fin and not impossible do begin
   if s[baris,kolom] < 9 then begin
      repeat
         s[baris,kolom] := s[baris,kolom] + 1;
      until (verifikasi_baris(baris) and verifikasi_kolom(kolom)
                  and verifikasi_sudoku(baris,kolom))
               or (s[baris,kolom] = 10);
      if s[baris,kolom] < 10 then fin := not sudo_maju;
   end else begin
      s[baris,kolom] := 0;
      impossible := not sudo_back;
   end;
end;
if fin then sudoku := true;
if impossible then sudoku := false;
end;

function verif : boolean;
var t : boolean;
begin
   t := true;
   for baris := 1 to 9 do
      for kolom := 1 to 9 do begin
         t := t and verifikasi_baris(baris);
         t := t and verifikasi_kolom(kolom);
         t := t and verifikasi_sudoku(baris,kolom);
      end;
   verif := t;
end;


begin
   randomize;
   clrscr;
   repeat
      repeat
         for baris := 1 to 9 do
            for kolom :=1 to 9 do begin
               s[baris,kolom] := 0;
               init[baris,kolom] := false;
            end;
         for i := 1 to 10 do begin
            baris := random(9) + 1;
            kolom := random(9) + 1;
            s[baris,kolom] := random(9) + 1;
            init[baris,kolom] := true;
         end;
      until verif;
      baris := 0; kolom := 9;
      sudo_maju;
   until sudoku;

   for baris := 1 to 9 do
      for kolom := 1 to 9 do begin
         mem[baris,kolom] := s[baris,kolom];
         init[baris,kolom] := true;
      end;

   for baris := 1 to 9 do
      for kolom := 1 to 9 do
         if not init[baris,kolom] then
            s[baris,kolom] := 0;
   make_box;
   readln(chemin);
   for baris := 1 to 9 do
       for kolom := 1 to 9 do
          s[baris,kolom] := mem[baris,kolom];
   make_box;

end.

